import Taro from '@tarojs/taro'
import API_GATHER from '../api/index'
import URL_CONFIG from './ipconfig'
import request from './create_request'
import { AllApiinterface, OuterParams, OuterOptions, ModoifyData } from '../config/interface'

interface RequestFn {
  [propName: string]: (outerParams?: OuterParams, outerOptions?: OuterOptions) => Promise<any>
}

class HttpApi {
  public api: RequestFn
  instance: null | HttpApi
  static instance: HttpApi
  constructor(api_gather: AllApiinterface) {
    this.api = {}
    this.instance = null
    this.init(api_gather)
  }
  private init(api_gather) {
    Object.keys(api_gather).map((namespce) => {
      this.createQuest({ namespce, config: api_gather[namespce] })
    })
  }
  private createQuest({ namespce, config }) {
    config.map((item) => {
      const { name, method, desc, path, params, host } = item
      const apiName = `${namespce}/${name}`
      const addignData = {
        path,
        desc,
        method,
        host
      }
      Object.defineProperty(this.api, apiName, {
        value(outerParams?: OuterParams, outerOptions?: OuterOptions) {
          const data = { ...params, ...outerParams }
          const options = Object.assign(addignData, outerOptions)
          return request<ModoifyData>(HttpApi.modifyData(data, options))
        }
      })
    })
  }

  static modifyData(data: OuterParams, options: OuterOptions): ModoifyData {
    const _options = JSON.parse(JSON.stringify(options))
    const _data = Object.assign({}, data)
    const path = _options.path
    // 这里是如果传入apiHost，就用传入的域名，没有传入就用默认的域名
    if (options.host && URL_CONFIG[options.host].startsWith('http')) {
      _options.url = URL_CONFIG[_options.host] + path
    } else {
      _options.url = URL_CONFIG.baseUrl + path
    }
    delete _options.host
    delete _options.path
    // 如果配置了log_verify_code，就自动加入token
    const dataKeys = Object.keys(_data)
    if (dataKeys.includes('log_verify_code')) {
      _data['log_verify_code'] = Taro.getStorageSync('token')
    }
    _options.data = _data
    return _options
  }
  public static getInstance(api_gather) {
    if (!this.instance) {
      this.instance = new HttpApi(api_gather)
    }
    return this.instance
  }
}

const API: RequestFn = HttpApi.getInstance(API_GATHER)['api']

export default API
